#pragma once

#include "stdafx.h"

#include "core/event.h"
#include "core/logger.h"
#include "core/task.h"

#include "util/named.h"

namespace natrium {
	namespace core {
		class Engine;

		class System:
			public util::UniqueNamed
		{
		public:
			friend class Engine;

			struct SystemInitializing {
				SystemInitializing(System* s);
			
				System* mSystem;
			};

			struct SystemShuttingDown {
				SystemShuttingDown(System* s);
				System* mSystem;
			};

			struct SystemUpdater:
				public Task 
			{
				SystemUpdater(System* s, unsigned int taskFlags);

				virtual void run();
			
				System* mSystem;
			};

			System(const std::string& name, unsigned int taskFlags = Task::NONE);
			virtual ~System();

			virtual bool init();
			virtual void update();
			virtual void shutdown();

			template <typename T>
			void addSetting(const std::string& name_in_configfile, T* target_variable);

		protected:
			boost::program_options::options_description mSettings;
			EventChannel mChan;

		private:
			std::shared_ptr<SystemUpdater> mUpdater;

			unsigned int mTaskFlags;
		};

		template <typename T>
		void System::addSetting(const std::string& name, T* target) {
			std::stringstream sstr;
			sstr << getName() << "." << name;

			mSettings.add_options()
				(sstr.str().c_str(), boost::program_options::value<T>(target));
		}
	}
}